﻿using MQTTnet;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MQTTnet.Client;
using MQTTnet.Client.Options;
using System.Threading;
using workstation.model;
using System.Drawing.Drawing2D;
using workstation.utils;
using workstation.mqtt;
using workstation.constants;
using System.Speech.Synthesis;

namespace workstation
{
    public partial class KeyWorkstation : Form
    {
        private bool maxflag = false;
        private bool activeDisconnect = false;
        public int ReceivedCount = 0;
        private string PublishProto = "";
        private IMqttClient mqttClient = null;
        private static string AUTH_FOR_COMMANDTYPE = "auth";
        private static string KEYDISCONNECTED_FOR_COMMANDTYPE = "keyDisconnected";
        private static string KEYCONNECTED_FOR_COMMANDTYPE = "keyConnected";
        private List<TopicModel> topicModels = new List<TopicModel>();
        private BindingList<TopicModel> TopicModels_BL;
        private List<MessageItemModel> messageItemModels = new List<MessageItemModel>();
        private BindingList<MessageItemModel> MessageItemModels_BL;//=new BindingList<MessageItemModel>(messageItemModels);
        private MqttMessageAnalyzingProvider messageAnalyzingProvider;

        public KeyWorkstation()
        {
            InitializeComponent();
            this.MaximizedBounds = Screen.PrimaryScreen.WorkingArea;
            Init();
            TopicModels_BL = new BindingList<TopicModel>(topicModels);
            MessageItemModels_BL = new BindingList<MessageItemModel>(messageItemModels);

        }
        /// <summary>
        /// 初始化
        /// </summary>

        public void Init()
        {
            this.tabControl1.Enabled = false;
            this.B_Disconnect.Enabled = false;
            PublishProto = "QoS0";
            B_Connect.Enabled = true;
            B_Disconnect.Enabled = false;
            ReceivedCount = 0;
            try
            {
                //B_Disconnect_Click(null,null);
            }
            catch (Exception ex)
            {

                //throw;
            }
        }
        /// <summary>
        /// 设置连接状态
        /// </summary>
        /// <param name="Status"></param>
        public void SetConnecttionStatus(bool Status)
        {
            if (Status)
            {
                this.SPB_StatusLight.BackColor = Color.GreenYellow;
                this.B_Connect.Enabled = false;
                this.tabControl1.Enabled = true;
                this.B_Disconnect.Enabled = true;
            }
            else
            {
                this.SPB_StatusLight.BackColor = Color.Gray;
                this.B_Connect.Enabled = true;
                this.tabControl1.Enabled = false;
                this.B_Disconnect.Enabled = false;
            }
        }
        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <returns></returns>
        private async Task ConnectMqttServerAsync()
        {
            try
            {
                string username = this.STB_Username.Text.Trim();
                string password = this.STB_Password.Text.Trim();
                string clientTag = this.STB_ClientTag.Text.Trim();
                GlobalConstant.CLIENT_TAG = clientTag;
                string clientName = MqttUntils.getValueFromINI("CLIENTNAME");
                string subscribeTopic = MqttUntils.getValueFromINI("SUBSCRIBETOPIC");
                string receiveTopic = subscribeTopic + clientTag;
                if (string.IsNullOrEmpty(username))
                {
                    MessageBox.Show("账号不能为空！");
                    return;
                }
                if (string.IsNullOrEmpty(password))
                {
                    MessageBox.Show("密码不能为空！");
                    return;
                }
                if (string.IsNullOrEmpty(clientTag))
                {
                    MessageBox.Show("用户标识不能为空！");
                    return;
                }
                if (string.IsNullOrEmpty(receiveTopic))
                {
                    MessageBox.Show("接收主题不能为空！");
                    return;
                }
                var factory = new MqttFactory();
                mqttClient = factory.CreateMqttClient();
                var options = new MqttClientOptionsBuilder()
                        .WithTcpServer(this.STB_IP.Text, Convert.ToInt32(this.STB_Port.Text)).WithCredentials(username, password).WithClientId(clientTag) // Port is optional
                        .Build();

                mqttClient.UseDisconnectedHandler(async e => {
                    if (!activeDisconnect)
                    {
                        Console.WriteLine("与服务器断开连接");
                        Invoke((new Action(() =>
                        {
                            sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 与服务器断开连接！" + STB_IP.Text + Environment.NewLine);
                        })));
                        await Task.Delay(TimeSpan.FromSeconds(2));
                        try
                        {
                            await mqttClient.ConnectAsync(options);
                            Invoke((new Action(() =>
                            {
                                activeDisconnect = false;
                                sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 重新连接成功！" + STB_IP.Text + Environment.NewLine);
                                SetConnecttionStatus(true);

                            })));
                        }
                        catch (Exception exp)
                        {
                            Invoke((new Action(() =>
                            {
                                sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 重新连接服务器失败 Msg{exp}" + STB_IP.Text + Environment.NewLine);
                            })));
                            Console.Write($"重新连接服务器失败 Msg：{exp}");
                        }
                    }
                });
                await mqttClient.ConnectAsync(options, CancellationToken.None);
                Invoke((new Action(() =>
                {
                    activeDisconnect = false;
                    sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 连接到MQTT服务器成功！" + STB_IP.Text + Environment.NewLine);
                    SetConnecttionStatus(true);
                })));
                await Subscribe(receiveTopic);
                mqttClient.UseApplicationMessageReceivedHandler(e =>
                {

                    Invoke((new Action(() =>
                    {
                        MqttClient_ApplicationMessageReceived(null, e);

                    })));

                });

            }
            catch (Exception ex)
            {
                Invoke((new Action(() =>
                {
                    sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 连接到MQTT服务器失败！" + Environment.NewLine + ex.Message + Environment.NewLine);
                    SetConnecttionStatus(false);
                })));
            }
        }



        /// <summary>
        /// 监听主题
        /// </summary>
        /// <param name="topic"></param>
        /// <returns></returns>
        private async Task Subscribe(string topic)
        {

            if (string.IsNullOrEmpty(topic))
            {
                MessageBox.Show("订阅主题不能为空！");
                return;
            }

            if (!mqttClient.IsConnected)
            {
                MessageBox.Show("MQTT客户端尚未连接！");
                return;
            }

            // Subscribe to a topic
            await mqttClient.SubscribeAsync(new TopicFilterBuilder()

                .WithTopic(topic)
                .WithAtMostOnceQoS()
                .Build()
                );
            Invoke((new Action(() =>
            {
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 已订阅[{topic}]主题{Environment.NewLine}");
                this.TopicModels_BL.Add(new TopicModel
                {
                    Count = "0",
                    Topic = topic
                });
            })));

        }

        /// <summary>
        /// 播放指定次数的语音内容
        /// </summary>
        private void repeatSpeek(string content, int times) {
            string sumVoiceContent = "";
           for (int i = 1; i <= times; i++) {
                sumVoiceContent += content;
            }
            SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer();
            speechSynthesizer.Rate = -3;//阅读速度
            speechSynthesizer.Volume = 100;
            speechSynthesizer.SpeakAsync(sumVoiceContent);
        }
        
        /// <summary>
        /// 消息解析
        /// </summary>
        /// <param name="eventArgs"></param>
        private void mqttMessageResolver(MqttApplicationMessageReceivedEventArgs eventArgs)
        {
            string topic = eventArgs.ApplicationMessage.Topic;
            MqttApplicationMessage ApplicationMessage = eventArgs.ApplicationMessage;
            byte[] Payload = eventArgs.ApplicationMessage.Payload;
            string content = System.Text.Encoding.UTF8.GetString(Payload);
            MqttMessageModel mqttMessageModel = (MqttMessageModel)Newtonsoft.Json.JsonConvert.DeserializeObject(content, typeof(MqttMessageModel));
            string voiceContent = "";
            if (AUTH_FOR_COMMANDTYPE.Equals(mqttMessageModel.CommandType)) {
                voiceContent = "授权成功请领取钥匙,";
                repeatSpeek(voiceContent, 2);
            }
            else if (KEYDISCONNECTED_FOR_COMMANDTYPE.Equals(mqttMessageModel.CommandType)) {
                voiceContent =  "钥匙已被领取,,";
                repeatSpeek(voiceContent, 2);
            }
            else if (KEYCONNECTED_FOR_COMMANDTYPE.Equals(mqttMessageModel.CommandType))
            {
                voiceContent = "钥匙已连接,,";
                repeatSpeek(voiceContent, 2);
            }
        }

        /// <summary>
        /// 收到mqtt消息
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="eventArgs"></param>
        private void MqttClient_ApplicationMessageReceived(object sender, MqttApplicationMessageReceivedEventArgs eventArgs)
        {
            ReceivedCount++;
            Invoke((new Action(() =>
            {
                if (TopicModels_BL.Where(item => item.Topic == eventArgs.ApplicationMessage.Topic).ToList().Count == 1)
                {
                    TopicModel topicModel = TopicModels_BL.Where(item => item.Topic == eventArgs.ApplicationMessage.Topic).FirstOrDefault();
                    int count = Convert.ToInt32(topicModel.Count);
                    topicModel.Count = (count + 1).ToString();
                }

                MessageItemModels_BL.Add(new MessageItemModel()
                {
                    TopicItem = eventArgs.ApplicationMessage.Topic,
                    Index = ReceivedCount.ToString(),
                    Type = eventArgs.ApplicationMessage.QualityOfServiceLevel.ToString(),
                    Attribute = "Retained"
                });

                //消息解析
                mqttMessageResolver(eventArgs);
                string countLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 第{ReceivedCount}条数据{Environment.NewLine}");
                LogHelper.WriteInfoLog(countLog);
                this.mqtt_message.AppendText(countLog);
                string applicationLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> {"### 收到应用消息 ###"}{Environment.NewLine}");
                LogHelper.WriteInfoLog(applicationLog);
                this.mqtt_message.AppendText(applicationLog);
                string topicLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> Topic = {eventArgs.ApplicationMessage.Topic}{Environment.NewLine}");
                LogHelper.WriteInfoLog(topicLog);
                this.mqtt_message.AppendText(topicLog);
                string payloadcLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> Payload = {Encoding.UTF8.GetString(eventArgs.ApplicationMessage.Payload)}{Environment.NewLine}");
                LogHelper.WriteInfoLog(payloadcLog);
                this.mqtt_message.AppendText(payloadcLog);
                string qosLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> QoS = {eventArgs.ApplicationMessage.QualityOfServiceLevel}{Environment.NewLine}");
                LogHelper.WriteInfoLog(qosLog);
                this.mqtt_message.AppendText(qosLog);
                string retainLog = LogFormat.generateLog($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> Retain = {eventArgs.ApplicationMessage.Retain}{Environment.NewLine}");
                LogHelper.WriteInfoLog(retainLog);
                this.mqtt_message.AppendText(retainLog);
            })));

            //限制richtextbox长度
            if (this.sys_message.Lines.Length > 50)
            {
                int moreLines = this.sys_message.Lines.Length - 50;
                string[] lines = this.sys_message.Lines;
                Array.Copy(lines, moreLines, lines, 0, 50);
                Array.Resize(ref lines, 50);
                this.sys_message.Lines = lines;
            }

        }
        /// <summary>
        /// 断开mqtt服务器
        /// </summary>
        /// <returns></returns>
        private async Task DisconnectMqttServerAsync()
        {
            if (mqttClient.IsConnected)
            {

            }
            else
            {
                Init();
                return;
            }
            Invoke((new Action(() =>
            {
                activeDisconnect = true;
                DateTime curTime = new DateTime();
                curTime = DateTime.UtcNow;
                mqttClient.DisconnectAsync();
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> [{curTime.ToLongTimeString()}]" + Environment.NewLine);
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 已断开MQTT连接！" + Environment.NewLine);
                SetConnecttionStatus(false);
            })));
            int indexcount = 0;
            while (mqttClient.IsConnected)
            {
                Thread.Sleep(50);
                //todo
            }
            Invoke((new Action(() =>
            {
                DateTime curTime = new DateTime();
                curTime = DateTime.UtcNow;
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> [{curTime.ToLongTimeString()}]" + Environment.NewLine);
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 已下线！" + Environment.NewLine);
                SetConnecttionStatus(false);
            })));
        }

        private void B_Connect_Click(object sender, EventArgs e)
        {
            Init();
            Task.Run(async () => { await ConnectMqttServerAsync(); });
        }


        private void B_Disconnect_Click(object sender, EventArgs e)
        {
            Task.Run(async () => { await DisconnectMqttServerAsync(); });


        }



        /// <summary>
        /// 连接mqtt服务器按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void B_Reconnect_Click(object sender, EventArgs e)
        {
            Invoke((new Action(() =>
            {
                this.sys_message.Clear();
                DateTime curTime = new DateTime();
                curTime = DateTime.UtcNow;
                mqttClient.DisconnectAsync();
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> [{curTime.ToLongTimeString()}]" + Environment.NewLine);
                this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 已断开MQTT连接！" + Environment.NewLine);
                SetConnecttionStatus(false);
            })));
        }

        /// <summary>
        /// 发布主题
        /// </summary>
        /// <param name="topic">主题</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        private async Task Publish(string topic, string content)
        {

            if (string.IsNullOrEmpty(topic))
            {
                MessageBox.Show("发布主题不能为空！");
                return;
            }


            try
            {
                var message = new MqttApplicationMessageBuilder()
                .WithTopic(topic)
                .WithPayload(content)
                .WithExactlyOnceQoS()
                .WithRetainFlag()
                .Build();

                await mqttClient.PublishAsync(message);
            }
            catch (Exception ex)
            {

                Invoke((new Action(() =>
                {
                    this.sys_message.AppendText($"{DateTime.Now.ToString(GlobalConstant.LOG_DATE_FORMAT)}>> 发布主题失败！" + Environment.NewLine + ex.Message + Environment.NewLine);
                })));
            }
        }

        private void B_ClearLog_Click(object sender, EventArgs e)
        {
            this.sys_message.Clear();
            //this.serial_message.Clear();
            this.mqtt_message.Clear();
        }

        public void PanelSizeChanged()
        {
            this.sysLog.Width = this.Size.Width;
            this.panel3.Width = this.Size.Width;
            this.mqttLog.Width = this.Size.Width;
           // this.serialLog.Width = this.Size.Width;
            this.tabControl1.Width = this.Size.Width;
            this.sys_message.Width = this.Size.Width;
        }

        private void KeyWorkstation_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Maximized)
            {
                if (!maxflag)
                {
                    this.WindowState = FormWindowState.Maximized;
                    this.PanelSizeChanged();
                    maxflag = true;
                }
                else
                {
                    this.WindowState = FormWindowState.Normal;
                    maxflag = false;
                }
            }

            //if (WindowState == FormWindowState.Minimized)
            //{
            //    MessageBox.Show("最小化");
            //}
        }

        private void KeyWorkstation_Load(object sender, EventArgs e)
        {
            GraphicsPath gp = new GraphicsPath();
            gp.AddEllipse(SPB_StatusLight.ClientRectangle);
            Region region = new Region(gp);
            SPB_StatusLight.Region = region;
            gp.Dispose();
            region.Dispose();
        }

        private void SPB_ClientServer_Click(object sender, EventArgs e)
        {

        }

        private void panel3_Paint(object sender, PaintEventArgs e)
        {

        }

        private void skinLabel4_Click(object sender, EventArgs e)
        {

        }

        private void SPB_StatusLight_Click(object sender, EventArgs e)
        {

        }

        private void STB_IP_Paint(object sender, PaintEventArgs e)
        {

        }

        private void STB_ClientTag_Paint(object sender, PaintEventArgs e)
        {

        }
    }
}
